﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ThermalEquipmentDesign.Model.Condenser.HorizontalPipeR12
{
    public class HorizontalPipeR12Model
    {
        HorizontalPipeR12Result res = new HorizontalPipeR12Result();
        HorizontalPipeR12 condenser;

        /// <summary>
        /// Calculate Horizontal Pipe Condenser
        /// </summary>
        /// <param name="con">HorizontalPipeR12 object</param>
        /// <returns>HorizontalPipeR12Result object</returns>
        public HorizontalPipeR12Result ImplementCalculation(HorizontalPipeR12 con)
        {
            condenser = con;
            res.dbCondensationTemp = CalculateCondensationTemp();
            res.dbHeatCapacity = CalculateHeatCapacity();
            res.dbWaterFlow = CalculateWaterFlow();
            res.dbPhiCoefficient = CalculatePhiCoefficient();
            res.dbPipeNumPerWay = CalculatePipeNumPerWay();
            res.dbReCoefficient = CalculateReCoefficient();
            res.dbMotionMode = CalculateMotionMode();
            res.dbHeatCoefficient = CalculateHeatCoefficient();
            res.dbHeatDensity = CalculateHeatDensity();
            res.dbPipeArea = CalculatePipeArea();
            res.dbDiagonalPipeNumber = CalculateDiagonalPipeNumber();
            res.dbTotalPipe = CalculateTotalPipe();
            res.dbWayNumber = CalculateWayNumber();
            res.dbReducedPipeNumber = CalculateReducedPipeNumber();
            res.dbRealPipeNumber = CalculateRealPipeNumber();
            res.dbPipeDiameter = CalculatePipeDiameter();
            res.dbHeatTransferArea = CalculateHeatTransferArea();
            res.dbPipeLenght = CalculatePipeLenght();
            return res;            
        }        

        /// <summary>
        /// Calculate condensation temperature
        /// </summary>
        /// <returns>condensation temperature</returns>
        private double CalculateCondensationTemp()
        {
            double t2 = condenser.dbCoolingTemp + condenser.dbDegreeIncreaseTemp;
            double e = Math.Pow(Math.E, condenser.dbDegreeIncreaseTemp / condenser.dbDiffTemp);
            double tk = (t2 * e - condenser.dbCoolingTemp) / (e - 1);
            return Math.Round(tk, 2);
        }

        /// <summary>
        /// Calculate heat capacity
        /// </summary>
        /// <returns>heat capacity</returns>
        private double CalculateHeatCapacity()
        {
            double Qk = 1.2 * condenser.dbColdProductivity;
            return Math.Round(Qk,2);
        }

        /// <summary>
        /// Calculate water flow
        /// </summary>
        /// <returns>water flow</returns>
        private double CalculateWaterFlow()
        {
            double Mn = res.dbHeatCapacity / (condenser.dbAverageWaterThermalCapacity * condenser.dbDegreeIncreaseTemp);
            return Math.Round(Mn, 2);
        }

        /// <summary>
        /// Calculate vane coefficient
        /// </summary>
        /// <returns>vane coefficient</returns>
        private double CalculatePhiCoefficient()
        {
            return Math.Round(condenser.dbExterArea / condenser.dbInterArea, 2);
        }

        /// <summary>
        /// Calculate number of pipe in a way
        /// </summary>
        /// <returns>number of pipe in a way</returns>
        private double CalculatePipeNumPerWay()
        {            
            double n1 = 4 * res.dbWaterFlow / (3.14 * Math.Pow(condenser.dbInterDiameter, 2) * condenser.dbDensity * condenser.dbWaterSpeed);
            return Math.Round(n1, 0);
        }

        /// <summary>
        /// Calculate Reynold coefficient
        /// </summary>
        /// <returns>Reynold coefficient</returns>
        private double CalculateReCoefficient()
        {
            double Re = (condenser.dbWaterSpeed * condenser.dbInterDiameter) / condenser.dbKinematicViscosity;
            return Math.Round(Re, 0);
        }

        /// <summary>
        /// Calculate motion mode
        /// </summary>
        /// <returns>motion mode</returns>
        private double CalculateMotionMode()
        {
            double Nu = 0.021 * Math.Pow(res.dbReCoefficient, 0.8) * Math.Pow(condenser.dbPrandtlCoefficient, 0.43);
            return Math.Round(Nu, 0);
        }

        /// <summary>
        /// Calculate calorific coefficient
        /// </summary>
        /// <returns>calorific coefficient</returns>
        private double CalculateHeatCoefficient()
        {
            return Math.Round(res.dbMotionMode * condenser.dbHeatConductivityCoefficient / condenser.dbInterDiameter, 2);
        }

        /// <summary>
        /// Calculate heat density to water
        /// </summary>
        /// <returns>heat density to water</returns>
        private double CalculateHeatDensity()
        {
            double Tu = 0.3 * condenser.dbDiffTemp;
            double A = 1 / ((1 / res.dbHeatCoefficient) + condenser.dbThermalResistance);
            double q2 = A * (condenser.dbDiffTemp - Tu);
            return Math.Round(q2, 2);
        }

        /// <summary>
        /// Calculate horizontal pipe pitch
        /// </summary>
        /// <returns></returns>
        private double CalculatePipeArea()
        {
            double S = 1.3 * condenser.dbExterDiameter;
            return Math.Round(S,2);
        }

        /// <summary>
        /// Calculate number of pipe in the big diagonal
        /// </summary>
        /// <returns>number of pipe in the big diagonal</returns>
        private double CalculateDiagonalPipeNumber()
        {            
            double can = res.dbHeatCapacity * Math.Pow(10, 3) / (res.dbHeatDensity * res.dbPipeArea * condenser.dbInterDiameter * 8);
            double can3 = Math.Pow(can, 1.0 / 3);
            double m = 0.75 * can3;
            return Math.Round(m, 2);
        }

        /// <summary>
        /// Calculate total of pipe
        /// </summary>
        /// <returns>total of pipe</returns>
        private double CalculateTotalPipe()
        {
            double n = 0.75 * Math.Pow(res.dbDiagonalPipeNumber, 2) + 0.25;
            return Math.Round(n,0);
        }

        /// <summary>
        /// Calculate number of water way
        /// </summary>
        /// <returns>number of water way</returns>
        private double CalculateWayNumber()
        {
            double z = res.dbTotalPipe / res.dbPipeNumPerWay;
            return Math.Round(z,2);
        }

        /// <summary>
        /// Calculate number of reduced pipe
        /// </summary>
        /// <returns>number of reduced pipe</returns>
        private double CalculateReducedPipeNumber()
        {
            double nb = 3 * (res.dbDiagonalPipeNumber + 1) / 2 + 3;
            return Math.Round(nb,0);
        }

        /// <summary>
        /// Calculate the actual number of pipe
        /// </summary>
        /// <returns>the actual number of pipe</returns>
        private double CalculateRealPipeNumber()
        {
            return Math.Round(res.dbTotalPipe - res.dbReducedPipeNumber,0);
        }

        /// <summary>
        /// Calculate diameter of pipes
        /// </summary>
        /// <returns>diameter of pipes</returns>
        private double CalculatePipeDiameter()
        {
            double S = 1.3 * condenser.dbExterDiameter;
            return Math.Round(res.dbDiagonalPipeNumber * S,2);
        }

        /// <summary>
        /// Calculate area of heat transfer surface 
        /// </summary>
        /// <returns>area of heat transfer surface </returns>
        private double CalculateHeatTransferArea()
        {
            return Math.Round(res.dbHeatCapacity * Math.Pow(10, 3) / res.dbHeatDensity,2);
        }

        /// <summary>
        /// Calculate lenght of pipe
        /// </summary>
        /// <returns>lenght of pipe</returns>
        private double CalculatePipeLenght()
        {
            double l = res.dbHeatTransferArea / (3.14 * condenser.dbExterDiameter * res.dbTotalPipe);
            return Math.Round(l,2);
        }

    }
}
